package com.quan.system.web.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.quan.common.annotation.Log;
import com.quan.common.bean.ResultBean;
import com.quan.common.core.MyBaseController;
import com.quan.common.enums.LogType;
import com.quan.common.utils.DateUtils;
import com.quan.common.utils.JwtTokenUtils;
import com.quan.common.utils.PasswordUtils;
import com.quan.common.utils.RedisOperator;
import com.quan.system.common.dto.LoginUserDTO;
import com.quan.system.entity.SystemPermission;
import com.quan.system.entity.SystemRole;
import com.quan.system.entity.SystemRolePermission;
import com.quan.system.entity.SystemUser;
import com.quan.system.service.SystemRolePermissionService;
import com.quan.system.service.SystemUserService;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;

@RestController
@RequestMapping("/sso")
public class SSOContoller extends MyBaseController {
	
	@Autowired
	private SystemUserService systemUserService;

	@Autowired
	private SystemRolePermissionService rolePermissionService;

	@Autowired
	private RedisOperator redisOperator;

	/**
	 * JwtToken秘钥
	 */
	@Value("${jwt.secret:123456}")
	private String jwtSecret;

	/**
	 * JwtToken过去时间（秒）
	 */
	@Value("${jwt.timeout:1800}")
	private Long timeout;

	@Log(type=LogType.LOGIN)
	@PostMapping("/login")
	public ResultBean login(@RequestBody LoginUserDTO login) {
		SystemUser user = this.systemUserService.findByUsername(login.getUsername());
		if (null != user) {
			// 判断账号是否锁定
			if (!user.getStatus()) {
				return ResultBean.failure("账号已锁定，请联系管理员！");
			}
			// 验证密码是否正确
			if (!PasswordUtils.isPasswordValid(user.getPassword(), login.getPassword(), user.getSalt())) {
				return ResultBean.failure("密码不正确！");
			}
			user.setPassword(null);

			Map<String, Object> claims = new HashMap<String, Object>();
			claims.put("sub", user.getUsername());
			claims.put("ctime", DateUtils.getMillis(new Date()));
			claims.put("exp", DateUtils.addMinute(timeout.intValue()));
			claims.put("user", user);
			claims.put("userId", user.getId()+"");
			claims.put("username", user.getUsername());
			claims.put("realname", user.getRealname());
			claims.put("isAdmin", user.getSuperAdmin());
			// 生成JWT Token
			String token = JwtTokenUtils.createToken(claims, jwtSecret);
			
			
			Map<String, Object> userInfo = new HashMap<String, Object>() ;
			// 获取用户角色
			List<SystemRole> roles = this.systemUserService.findRolesByUserId(user.getId());
			
			// 获取用户权限
			List<SystemPermission> permissions = this.systemUserService.findPermissionsByUserId(user.getId());
			List<String> access = new ArrayList<String>() ;
			for (SystemPermission permission : permissions) {
				access.add(permission.getPermission());
			}
			
			// 获取个人对应的权限关联关系
			List<SystemRolePermission> myPermissionRelation = null ;
			if(null != roles && !roles.isEmpty()) {
				List<Long> roleIds = new ArrayList<Long>() ;
				roles.forEach(item -> {
					roleIds.add(item.getId());
				});
				
				QueryWrapper<SystemRolePermission> queryWrapper = new QueryWrapper<SystemRolePermission>() ;
				queryWrapper.in("role_id", roleIds) ;
				myPermissionRelation = this.rolePermissionService.list(queryWrapper);
			}
			
			user.setPassword(null);
			userInfo.put("user", user);
			userInfo.put("roles", roles);
			userInfo.put("permissions", permissions) ;
			userInfo.put("access", access) ;
			userInfo.put("myPermissionRelation", myPermissionRelation) ;
			
			// 将Token 保存到Redis缓存中
			this.redisOperator.set("sso:token:" + user.getId(), token, timeout);
			
			Map<String, Object> map = new HashMap<String, Object>() ;
			map.put("token", token);
			map.put("userinfo", userInfo);
			
			return ResultBean.ok("登录成功", map);
		} else {
			return ResultBean.failure("账号不存在");
		}
	}
	
	
	@Log(type=LogType.LOGOUT)
	@GetMapping("/logout")
	public boolean logout() {
		String token = this.request.getHeader("Auth-Token");

		// Token为空，缓存中已没有改用户数据
		if (null == token || "".equals(token.trim())) {
			return true;
		}

		Jws<Claims> parse = JwtTokenUtils.parse(token, jwtSecret);
		if (null != parse) {
			Claims body = parse.getBody();

			this.redisOperator.del("sso:token:" + body.get("userId"));
			return true ;
		} else {
			logger.info("Token解析失败");
			return false;
		}
	}
	
	@GetMapping("/validToken")
	public boolean validToken() {
		String token = this.request.getHeader("Auth-Token");
		
		// Token为空
		if (null == token || "".equals(token.trim())) {
			return false;
		}
		
		Jws<Claims> parse = JwtTokenUtils.parse(token, jwtSecret);
		if (null != parse) {
			Claims body = parse.getBody();
			boolean hasKey = this.redisOperator.hasKey("sso:token:" + body.get("userId"));
			if(hasKey) {
				this.redisOperator.expire("sso:token:" + body.get("userId"), timeout);
				return true ;
			} else {
				return false ;
			}
		} else {
			logger.info("Token解析失败");
			return false;
		}
	}

}
